<script lang="ts" setup>
import { PropType } from 'vue'
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
import { i18nChangeLanguage, IDomEditor, IEditorConfig } from '@wangeditor/editor'
import { propTypes } from '@/utils/propTypes'
import { isNumber } from '@/utils/is'
import { ElMessage } from 'element-plus'
import { useLocaleStore } from '@/store/modules/locale'
import { getRefreshToken, getTenantId } from '@/utils/auth'
import { getUploadUrl } from '@/components/UploadFile/src/useUpload'
import axios from 'axios' // 确保已安装axios

defineOptions({ name: 'Editor' })

type InsertFnType = (url: string, alt: string, href: string) => void

const localeStore = useLocaleStore()

const currentLocale = computed(() => localeStore.getCurrentLocale)

i18nChangeLanguage(unref(currentLocale).lang)

const props = defineProps({
  editorId: propTypes.string.def('wangeEditor-1'),
  height: propTypes.oneOfType([Number, String]).def('500px'),
  editorConfig: {
    type: Object as PropType<Partial<IEditorConfig>>,
    default: () => undefined
  },
  readonly: propTypes.bool.def(false),
  modelValue: propTypes.string.def('')
})

const emit = defineEmits(['change', 'update:modelValue'])

// 编辑器实例，必须用 shallowRef
const editorRef = shallowRef<IDomEditor>()

const valueHtml = ref('')
// 新增状态
const fileInputRef = ref<HTMLInputElement | null>(null)
const isDragging = ref(false)
const selectAll = ref(false)
// 上传相关状态
const showUploadDialog = ref(false)
const pendingFiles = ref<Array<{ file: File; url: string , selected: boolean, id: number }>>([])
const uploadType = ref<'image' | 'video'>('image')
// 新增状态：记录选中顺序
const selectedOrder = ref<number[]>([])
// 打开文件选择器
const openFileSelector = () => {
  fileInputRef.value?.click()
  console.log(fileInputRef.value,'fileInputRef.value');
  
}
// 处理文件选择
const handleFileChange = (e: Event) => {
  const files = Array.from((e.target as HTMLInputElement).files || [])
  if (files.length > 0) {
    addFiles(files)
  }
}
// 处理拖放
const handleDragOver = (e: DragEvent) => {
  e.preventDefault()
  isDragging.value = true
}
const handleDragLeave = () => {
  isDragging.value = false
}

const handleDrop = (e: DragEvent) => {
  e.preventDefault()
  isDragging.value = false
  const files = Array.from(e.dataTransfer?.files || [])
  if (files.length > 0) {
    addFiles(files)
  }
}

// 添加文件到待上传列表
const addFiles = (files: File[]) => {
  const validFiles = files.filter(file => {
    if (uploadType.value === 'image') {
      return ['image/jpeg', 'image/png', 'image/gif'].includes(file.type)
    } else {
      return file.type.startsWith('video/')
    }
  })

  if (validFiles.length === 0) {
    ElMessage.warning('请选择正确的文件格式')
    return
  }

  pendingFiles.value = [
    ...pendingFiles.value,
    ...validFiles.map((file,index) => ({
      file,
      url: URL.createObjectURL(file),
      selected: false, // 添加选中状态
      id: Date.now() + index // 添加唯一ID
    }))
  ]
}

// 删除单个文件
const removeFile = (index: number) => {
  URL.revokeObjectURL(pendingFiles.value[index].url)
  pendingFiles.value.splice(index, 1)
}

// 全选/取消全选
const toggleSelectAll = () => {
  pendingFiles.value = pendingFiles.value.map((item, index) => {
    const newSelected = selectAll.value
    
    // 更新选中顺序
    if (newSelected && !item.selected) {
      selectedOrder.value.push(index)
    } else if (!newSelected && item.selected) {
      selectedOrder.value = selectedOrder.value.filter(i => i !== index)
    }
    
    return {
      ...item,
      selected: newSelected
    }
  })
}
// 获取文件选中序号
const getSelectedIndex = (index: number) => {
  if (!pendingFiles.value[index].selected) return 0
  return selectedOrder.value.indexOf(index) + 1
}
// 删除选中的文件
const removeSelected = () => {
  if (selectAll.value) {
    pendingFiles.value.forEach(item => URL.revokeObjectURL(item.url))
    pendingFiles.value = []
  } else {
    // 如果有部分选中逻辑可以在这里实现
  }
  selectAll.value = false
}
watch(
  () => props.modelValue,
  (val: string) => {
    if (val === unref(valueHtml)) return
    valueHtml.value = val
  },
  {
    immediate: true
  }
)

// 监听
watch(
  () => valueHtml.value,
  (val: string) => {
    emit('update:modelValue', val)
  }
)

const handleCreated = (editor: IDomEditor) => {
  editorRef.value = editor
}

// 编辑器配置
const editorConfig = computed((): IEditorConfig => {
  return Object.assign(
    {
      placeholder: '请输入内容...',
      readOnly: props.readonly,
      customAlert: (s: string, t: string) => {
        switch (t) {
          case 'success':
            ElMessage.success(s)
            break
          case 'info':
            ElMessage.info(s)
            break
          case 'warning':
            ElMessage.warning(s)
            break
          case 'error':
            ElMessage.error(s)
            break
          default:
            ElMessage.info(s)
            break
        }
      },
      autoFocus: false,
      scroll: true,
      MENU_CONF: {
        ['uploadImage']: {
          server: getUploadUrl(),
          // 单个文件的最大体积限制，默认为 2M
          maxFileSize: 5 * 1024 * 1024,
          // 最多可上传几个文件，默认为 100
          maxNumberOfFiles: 10,
          // 选择文件时的类型限制，默认为 ['image/*'] 。如不想限制，则设置为 []
          allowedFileTypes: ['image/*'],

          // 自定义增加 http  header
          headers: {
            Accept: '*',
            Authorization: 'Bearer ' + getRefreshToken(), // 使用 getRefreshToken() 方法，而不使用 getAccessToken() 方法的原因：Editor 无法方便的刷新访问令牌
            'tenant-id': getTenantId()
          },

          // 超时时间，默认为 10 秒
          timeout: 15 * 1000, // 15 秒

          // form-data fieldName，后端接口参数名称，默认值wangeditor-uploaded-image
          fieldName: 'file',
          // 点击上传本地图片按钮时触发
          customBrowseAndUpload: (insertFn: InsertFnType) => {
            showUploadDialog.value = true     
              // 清空上传列表
            pendingFiles.value = []
            // 清空选中状态
            selectAll.value = false
            // 清空选中顺序
            selectedOrder.value = []
            uploadType.value = 'image'
          },
          // 上传之前触发
          onBeforeUpload(file: File) {
            // console.log(file)
            return file
          },
          // 上传进度的回调函数
          onProgress(progress: number) {
            // progress 是 0-100 的数字
            console.log('progress', progress)
          },
          onSuccess(file: File, res: any) {
            console.log('onSuccess', file, res)
          },
          onFailed(file: File, res: any) {
            alert(res.message)
            console.log('onFailed', file, res)
          },
          onError(file: File, err: any, res: any) {
            alert(err.message)
            console.error('onError', file, err, res)
          },
          // 自定义插入图片
          customInsert(res: any, insertFn: InsertFnType) {
            insertFn(res.data, 'image', res.data)
          }
        },
        ['uploadVideo']: {
          server: getUploadUrl(),
          // 单个文件的最大体积限制，默认为 10M
          maxFileSize: 10 * 1024 * 1024,
          // 最多可上传几个文件，默认为 100
          maxNumberOfFiles: 10,
          // 选择文件时的类型限制，默认为 ['video/*'] 。如不想限制，则设置为 []
          allowedFileTypes: ['video/*'],

          // 自定义增加 http  header
          headers: {
            Accept: '*',
            Authorization: 'Bearer ' + getRefreshToken(), // 使用 getRefreshToken() 方法，而不使用 getAccessToken() 方法的原因：Editor 无法方便的刷新访问令牌
            'tenant-id': getTenantId()
          },

          // 超时时间，默认为 30 秒
          timeout: 15 * 1000, // 15 秒

          // form-data fieldName，后端接口参数名称，默认值wangeditor-uploaded-image
          fieldName: 'file',
           // 点击上传本地图片按钮时触发
          customBrowseAndUpload: (insertFn: InsertFnType) => {
            showUploadDialog.value = true     
              // 清空上传列表
            pendingFiles.value = []
            // 清空选中状态
            selectAll.value = false
            // 清空选中顺序
            selectedOrder.value = []
            uploadType.value = 'video'
          },
          // 上传之前触发
          onBeforeUpload(file: File) {
            // console.log(file)
            return file
          },
          // 上传进度的回调函数
          onProgress(progress: number) {
            // progress 是 0-100 的数字
            console.log('progress', progress)
          },
          onSuccess(file: File, res: any) {
            console.log('onSuccess', file, res)
          },
          onFailed(file: File, res: any) {
            alert(res.message)
            console.log('onFailed', file, res)
          },
          onError(file: File, err: any, res: any) {
            alert(err.message)
            console.error('onError', file, err, res)
          },
          // 自定义插入图片
          customInsert(res: any, insertFn: InsertFnType) {
            insertFn(res.data, 'mp4', res.data)
          }
        }
      },
      uploadImgShowBase64: true
    },
    props.editorConfig || {}
  )
})
// 上传文件函数
const uploadFile = async (file: File, type: 'image' | 'video') => {
  const formData = new FormData()
  formData.append('file', file)
  
  const response = await axios.post(getUploadUrl(), formData, {
    headers: {
      'Content-Type': 'multipart/form-data',
      'Authorization': 'Bearer ' + getRefreshToken(),
      'tenant-id': getTenantId(),
      // 可以根据类型添加不同header
      'X-File-Type': type
    },
    // 上传进度回调（如果需要）
    // onUploadProgress: (progressEvent) => {
    //   const percentCompleted = Math.round(
    //     (progressEvent.loaded * 100) / (progressEvent.total || 1),
    //   // console.log(`上传进度: ${percentCompleted}%`)
    //   )
    // }
  })
  
  return response.data
}

// 修改后的上传逻辑
const confirmUpload = async () => {
  if (!editorRef.value || pendingFiles.value.length === 0) return

   // 按照选中顺序获取文件（selectedOrder中记录的index顺序）
  const filesToUpload = selectedOrder.value.map(index => pendingFiles.value[index]).filter(Boolean) // 过滤掉可能不存在的索引

  if (filesToUpload.length === 0) {
    ElMessage.warning('请至少选择一个文件上传')
    return
  }
 const loading = ElLoading.service({
    lock: true,
    text: `正在上传选中的 ${filesToUpload.length} 个文件...`,
    background: 'rgba(0, 0, 0, 0.7)'
  })

  try {
    const successUrls: string[] = []
    
    for (const item of filesToUpload) {
      try {
        // 调用上传接口
        const res = await uploadFile(item.file, uploadType.value)
        
        const fileUrl = res.data
        
        // 插入到编辑器
        if (uploadType.value === 'image') {
          editorRef.value.insertNode({
            type: 'image',
            src: fileUrl,
            alt: item.file.name,
            children: [{ text: '' }]
          })
        } else {
          editorRef.value.insertNode({
            src: fileUrl,
            type: 'video',
            alt: item.file.name,
            children: [{ text: '' }]
          })
        }
        successUrls.push(fileUrl)
        // 在图片后插入换行（段落）
        editorRef.value.insertNode({
          type: 'paragraph',
          children: [{ text: '' }] // 空段落即换行
        });
        console.log('successUrls',successUrls);
      } catch (error) {
        // console.error(`文件 ${item.file.name} 上传失败:`, error)
        // ElMessage.error(`文件 ${item.file.name} 上传失败`)
      }
    }

    if (successUrls.length > 0) {
      ElMessage.success(`成功上传 ${successUrls.length}/${filesToUpload.length} 个文件`)
    } else {
      ElMessage.warning('没有文件上传成功')
    }
  } catch (error) {
    console.error('上传出错:', error)
    ElMessage.error('上传过程中出错')
  } finally {
    loading.close()
    pendingFiles.value.forEach(item => URL.revokeObjectURL(item.url))
    pendingFiles.value = []
    showUploadDialog.value = false
  }
  selectedOrder.value = []
}
const editorStyle = computed(() => {
  return {
    height: isNumber(props.height) ? `${props.height}px` : props.height
  }
})
const handleSelectFile = (index: number) => {
// 单个盒子选中
  toggleFileSelect(index)
}
// 单个文件选中状态切换
const toggleFileSelect = (index: number) => {
   const isSelected = !pendingFiles.value[index].selected
  pendingFiles.value[index].selected = isSelected
  // 更新选中顺序
  if (isSelected) {
    selectedOrder.value.push(index)
  } else {
    selectedOrder.value = selectedOrder.value.filter(i => i !== index)
  }
  
  // 检查是否全部选中
  selectAll.value = pendingFiles.value.every(item => item.selected)
}
// 回调函数
const handleChange = (editor: IDomEditor) => {
  emit('change', editor)
}

// 组件销毁时，及时销毁编辑器
onBeforeUnmount(() => {
  const editor = unref(editorRef.value)

  // 销毁，并移除 editor
  editor?.destroy()
})

const getEditorRef = async (): Promise<IDomEditor> => {
  await nextTick()
  return unref(editorRef.value) as IDomEditor
}

defineExpose({
  getEditorRef
})
</script>

<template>
  <div class="border-1 border-solid border-[#ccc] z-10">
    <!-- 工具栏 -->
    <Toolbar
      :editor="editorRef"
      :editorId="editorId"
      class="border-0 b-b-1 border-solid border-[#ccc]"
    />
    <!-- 编辑器 -->
    <Editor
      v-model="valueHtml"
      :defaultConfig="editorConfig"
      :editorId="editorId"
      :style="editorStyle"
      @on-change="handleChange"
      @on-created="handleCreated"
    />

      <!-- 上传对话框 -->
    <el-dialog
      v-model="showUploadDialog"
      :title="`插入${uploadType === 'image' ? '图片' : '视频'}`"
      width="46%"
    >
      <!-- 无文件时的上传区域 -->
      <div 
        v-if="pendingFiles.length === 0"
        class="upload-area"
        @dragover="handleDragOver"
        @dragleave="handleDragLeave"
        @drop="handleDrop"
        :class="{ 'dragging': isDragging }"
        @click="openFileSelector"
      >
        <div class="upload-content">
          <Icon icon="ep:upload-filled" class="upload-icon"  />
          <!-- <el-icon :size="50" class="upload-icon">
            <Upload />
          </el-icon> -->
          <div class="upload-text" v-if="uploadType === 'image'">
            <p>支持选择多张5M以内jpg、jpeg、gif、png格式图片上传</p>
            <p>也可直接拖拽到此处进行上传</p>
          </div>
          <div  class="upload-text" v-if="uploadType === 'video'">
             <p>支持选择多张100M以内mp4、mov格式视频上传</p>
             <p>也可直接拖拽到此处进行上传</p>
          </div>
        </div>
        <input
          ref="fileInputRef"
          type="file"
          :accept="uploadType === 'image' ? 'image/*' : 'video/*'"
          multiple
          @change="handleFileChange"
          style="display: none"
        />
      </div>
      
      <!-- 有文件时的列表展示 -->
      <div v-else class="file-list-container">
        <div class="file-list-header">
          <el-checkbox v-model="selectAll" @change="toggleSelectAll">
            全选/反选
          </el-checkbox>
          <el-button type="primary" plain color="#3721ff" @click="openFileSelector">
            选择文件
          </el-button>
        </div>
        <div class="file-list">
          <div 
            v-for="(item, index) in pendingFiles" 
            :key="index" 
            class="file-item"
            @click.stop="handleSelectFile(index)"
            >
          <div class="file-selector">
            <el-checkbox 
              v-model="item.selected" 
              @change.self="toggleFileSelect(index)"
            />
          </div>
            <div class="file-preview">
              <img
                v-if="uploadType === 'image'"
                :src="item.url"
                class="preview-image"
              />
              <video 
                v-else
                :src="item.url"
                class="preview-video"
                ></video>
                <!-- controls -->
              <!-- 蒙层 -->
              <div v-if="item.selected" class="file-mask"></div>
            </div>
            <!-- <div class="file-info">
              <div class="file-name">{{ item.file.name }}</div>
              <div class="file-size">{{ (item.file.size / 1024 / 1024).toFixed(2) }}MB</div>
            </div> -->
             <!-- 序号 -->
             <Icon icon="ep:close" class="delete-icon" @click="removeFile(index)" />
             <div v-if="item.selected" class="file-index">
               {{ getSelectedIndex(index) }}
             </div>
         
          </div>
        </div>
        <input
          ref="fileInputRef"
          type="file"
          :accept="uploadType === 'image' ? 'image/*' : 'video/*'"
          multiple
          @change="handleFileChange"
          style="display: none"
        />
      </div>

      <template #footer>
        <el-button @click="showUploadDialog = false">取消</el-button>
        <el-button 
          type="primary" 
          color="#3721ff"
          @click="confirmUpload"
          :disabled="pendingFiles.length === 0"
        >
          确定上传 ({{ selectedOrder.length }})
        </el-button>
      </template>
    </el-dialog>
  </div>
</template>
<style scoped>
.upload-area {
  border: 2px dashed #dcdfe6;
  border-radius: 6px;
  padding: 40px;
  min-height: 400px;
  text-align: center;
  cursor: pointer;
  transition: all 0.3s;
  background-color: #fafafa;
}

.upload-area.dragging {
  border-color: #409eff;
  background-color: #f0f7ff;
}

.file-selector {
  position: absolute;
  top: -5px;
  left: 4px;
  z-index: 2;
}
.upload-content {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  padding-top: 10%;
  box-sizing: border-box;
}

.upload-icon {
  color: #8c939d;
}

.upload-text {
  color: #8c939d;
  font-size: 14px;
  line-height: 1.5;
}
.file-mask {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(22, 21, 21, 0.5);
  border-radius: 4px;
}
.file-list-container {
  display: flex;
  flex-direction: column;
  gap: 16px;
  min-height: 400px;
}

.file-list-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-bottom: 12px;
  border-bottom: 1px solid #ebeef5;
}

.file-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
  gap: 12px;
  max-height: 400px;
  overflow-y: auto;
}

.file-item {
  position: relative;
  border: 1px solid #ebeef5;
  border-radius: 4px;
  padding: 8px;
  transition: all 0.3s;
  cursor: pointer;
}

.file-item:hover {
  border-color: #409eff;

}
.w-e-text p:empty {
  display: none;
}
.file-preview {
  width: 100px;
  height: 100px;      
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
  
.preview-image {
  max-width: 100%;   
  max-height: 100%;  
  width: auto;      
  height: auto;     
  object-fit: contain; 
  display: block;
}

.preview-video {
  max-width: 100%;
  max-height: 100%;
}

.file-info {
  margin-top: 8px;
  font-size: 12px;
}

.file-name {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.file-size {
  color: #909399;
}

.delete-icon {
  position: absolute;
  top: 4px;
  right: 4px;
  padding: 4px;
  background-color: rgba(0, 0, 0, 0.5);
  color: white;
  border-radius: 50%;
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.3s;
}
.file-index{
  position: absolute;
  right: 4px;
  bottom: 4px;
  border-radius: 50%;
  background-color: #3721ff;
  color: #fff;
  width: 16px;
  font-size: 10px;
  height: 16px;
  padding: 4px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.file-item:hover .delete-icon {
  opacity: 1;
}
</style>

<style src="@wangeditor/editor/dist/css/style.css"></style>
